package com.guokai2012;


import com.guokai2012.domain.LineData;
import com.guokai2012.util.DataTipManager;
import com.guokai2012.util.ListPanelItem;
import com.guokai2012.util.MainFrame;
import com.guokai2012.util.PropertiesManager;

import javax.script.ScriptEngineManager;
import javax.swing.*;
import java.awt.*;
import java.io.*;
import java.nio.charset.StandardCharsets;
import java.util.List;
import java.util.Map;
import java.util.TimerTask;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;

/**
 * 主程序
 */
public class TodoListMain {
    private String proPath;
    private String iconPath;
    private String tipPath;

    private final MainFrame frame;
    private ListPanelItem panelItem;
    private DataTipManager storage;
    private PropertiesManager proManager;

    public TodoListMain() {
        getFilePath();
        this.frame = new MainFrame("事项提醒", 600, 600, Color.WHITE);
    }

    public void Start(String[] args) {
        // 设置主窗口
        this.proManager = new PropertiesManager(proPath);
        frame.initMyJFrame(iconPath, proManager);
        frame.setVisible(true);
        this.storage = new DataTipManager(tipPath, proManager);
        this.panelItem = new ListPanelItem(frame, "yyyy-MM-dd HH:mm");
        panelItem.addCommitted(new Consumer<ListPanelItem>() {
            @Override
            public void accept(ListPanelItem listPanelItem) {
                storage.outTipData(panelItem.getDataList());
            }
        });
        frame.getContentPane().add(panelItem);
        initDataTip();

        List<LineData> data = storage.getTipData();
        panelItem.initListPanelItem(data);
        doCheckTip();
        shutDown();
    }

    private void initDataTip() {
        storage.initTip(new Consumer<Map<String, Object>>() {
            @Override
            public void accept(Map<String, Object> map) {
                int code = Integer.parseInt(map.get("code").toString());
                String message = String.valueOf(map.get("message"));
                if (200 != code) {
                    System.out.println(code + " -> " + message);
                    frame.setVisible(true);
                    if (502 == code) {
                        int ci = JOptionPane.showConfirmDialog(frame, message, "信息确认", JOptionPane.YES_NO_OPTION);
                        if (ci == JOptionPane.YES_OPTION) {
                            initDataTip();
                        }
                    } else {
                        showWarning(message);
                    }
                } else {
                    frame.minimizeToTray();
                }
            }
        });
    }

    private void getFilePath() {
        String protocol = TodoListMain.class.getResource("").getProtocol();
        if ("jar".equals(protocol)) {
            String filePath = TodoListMain.class.getProtectionDomain().getCodeSource().getLocation().getPath();
            String path = filePath.substring(0, filePath.lastIndexOf("/")) + "/";
            this.tipPath = path + "tmpfile/tipData.txt";
            this.iconPath = path + "image/reminders.png";
            this.proPath = path + "config/todoList.properties";
            fileExists(tipPath, "tmpfile/tipData.txt");
            fileExists(iconPath, "image/reminders.png");
            fileExists(proPath, "config/todoList.properties");
            fileExists(path + "start.bat", "");
            fileExists(path + "start.vbs", "");
        } else {
            String path = TodoListMain.class.getClassLoader().getResource("").getPath();
            this.tipPath = path + "tmpfile/tipData.txt";
            this.iconPath = path + "image/reminders.png";
            this.proPath = path + "config/todoList.properties";
        }
    }

    /**
     * 处理，将JAR包下的配置文件，复制到JAR包外
     */
    private void fileExists(String path, String jarPath) {
        File file = new File(path);
        String name = file.getName();
        String absolutePath = file.getParent();
        if (!file.exists()) {
            String winPaht = absolutePath.replaceAll("/", "\\") + "\\";
            if ("start.bat".equals(name) || "start.vbs".equals(name)) {
                if ("start.bat".equals(name)) {
                    File tmpLog = new File(winPaht + "log");
                    tmpLog.mkdirs();
                }
                String str = "@echo off\r\n" +
                        "set name=todo-list.jar\r\n" +
                        "for /f \"usebackq tokens=1,2\" %%a in (`jps -l ^|findstr %name%`) do (\r\n" +
                        "set pid=%%a\r\n" +
                        "set pname=%%b\r\n" +
                        ")\r\n" +
                        "if not defined pid (echo process %name% does not exists) else (\r\n" +
                        "rem 根据进程ID，kill进程\r\n" +
                        "taskkill /f /pid %pid%\r\n" +
                        ")\r\n" +
                        "rem 暂停2秒\r\n" +
                        "ping /n 2 127.1>nul\r\n" +
                        "set dt=%date:~0,4%%date:~5,2%%date:~8,2%\r\n" +
                        "java -jar " + winPaht + "todo-list.jar >> " + winPaht + "log\\log%dt%.txt\r\n" +
                        "exit";
                if ("start.vbs".equals(name)) {
                    str = "createobject(\"wscript.shell\").run\"" + winPaht + "start.bat\",0";
                }
                try (FileWriter out = new FileWriter(file)) {
                    out.write(str);
                    out.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                return;
            }

            // 创建文件夹
            File tmp = new File(absolutePath);
            if (tmp.mkdirs()) {
                try (FileOutputStream out = new FileOutputStream(file); InputStream in = TodoListMain.class.getClassLoader().getResourceAsStream(jarPath);) {
                    byte[] reads = new byte[1024];
                    int readCount;
                    while ((readCount = in.read(reads)) != -1) {
                        out.write(reads, 0, readCount);
                    }
                    out.flush();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
    }

    /**
     * 添加 退出处理
     */
    private void shutDown() {
        Runtime.getRuntime().addShutdownHook(new Thread() {
            @Override
            public void run() {
                storage.outTipData(panelItem.getDataList());
            }
        });
    }

    /**
     * 定时 检查是否需要弹出 任务提示
     */
    private void doCheckTip() {
        ScheduledExecutorService service = Executors.newScheduledThreadPool(1);
        service.scheduleAtFixedRate(new TimerTask() {
            @Override
            public void run() {
                List<LineData> todoList = panelItem.getDataList();
                long l = System.currentTimeMillis();
                for (int i = 0; i < todoList.size(); i++) {
                    if (null != todoList.get(i).getRemindTime() && !todoList.get(i).getFinish() && l >= todoList.get(i).getRemindTime().getTime()) {
                        panelItem.showTip(i);
                    }
                }
            }
        }, 0, 1, TimeUnit.MINUTES);

        if (proManager.getUpStep() >= 10) {
            service.scheduleWithFixedDelay(new TimerTask() {
                @Override
                public void run() {
                    storage.upLoad();
                }
            }, proManager.getUpStep(), proManager.getUpStep(), TimeUnit.MINUTES);
        }
    }

    /**
     * 显示错误提示
     */
    private void showWarning(String mess) {
        JOptionPane.showMessageDialog(frame, mess, "提示消息", JOptionPane.WARNING_MESSAGE);
        panelItem.updateUI();
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            @Override
            public void run() {
                new TodoListMain().Start(args);
            }
        });
    }
}
